//
//  main.m
//  DeepIntoKVO
//
//  Created by  on 12-11-15.
//  Copyright (c) 2012年 kesalin. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

#import "Target.h"
#import "Observer.h"
#import "Foo.h"
#import "TargetWrapper.h"

static NSArray * ClassMethodNames(Class c)
{
    NSMutableArray * array = [NSMutableArray array];
    
    unsigned int methodCount = 0;
    Method * methodList = class_copyMethodList(c, &methodCount);
    unsigned int i;
    for(i = 0; i < methodCount; i++) {
        [array addObject: NSStringFromSelector(method_getName(methodList[i]))];
    }

    free(methodList);
    
    return array;
}

static void PrintDescription(NSString * name, id obj)
{
    NSString * str = [NSString stringWithFormat:
                      @"\n\t%@: %@\n\tNSObject class %s\n\tlibobjc class %s\n\timplements methods <%@>",
                      name,
                      obj,
                      class_getName([obj class]),
                      class_getName(obj->isa),
                      [ClassMethodNames(obj->isa) componentsJoinedByString:@", "]];//这里要用isa指针才能看出端倪
    NSLog(@"%@", str);
}

int main (int argc, const char * argv[])
{

    @autoreleasepool {

        // KVO demo
        //
//        Observer * observer = [[[Observer alloc] init] autorelease];
//
//        Target * target = [[[Target alloc] init] autorelease];
//        [target addObserver:observer
//                 forKeyPath:@"age"
//                    options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
//                    context:[Target class]];
//
//        [target setAge:30];
//        //[target setValue:[NSNumber numberWithInt:30] forKey:@"age"];
//        [target removeObserver:observer forKeyPath:@"age"];


//        TargetWrapper * wrapper = [[[TargetWrapper alloc] init:target] autorelease];
//        [wrapper addObserver:observer
//                  forKeyPath:@"information"
//                     options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
//                     context:[TargetWrapper class]];//这一步会先判断依赖关系
//
//        [target setGrade:1];//猜想wrapper也时taget的一个观察着
//        [wrapper removeObserver:observer forKeyPath:@"information"];
        
        // Deep into KVO
        //
        Foo * anything = [[Foo alloc] init];
        Foo * x = [[Foo alloc] init];
        Foo * y = [[Foo alloc] init];
        Foo * xy = [[Foo alloc] init];
        Foo * control = [[Foo alloc] init];
        
        [x addObserver:anything forKeyPath:@"x" options:0 context:NULL];
        [y addObserver:anything forKeyPath:@"y" options:0 context:NULL];
        
        [xy addObserver:anything forKeyPath:@"x" options:0 context:NULL];
        [xy addObserver:anything forKeyPath:@"y" options:0 context:NULL];
        
        PrintDescription(@"control", control);
        PrintDescription(@"x", x);
        PrintDescription(@"y", y);
        PrintDescription(@"xy", xy);
        
        NSLog(@"\n\tUsing NSObject methods, normal setX: is %p, overridden setX: is %p\n",
               [control methodForSelector:@selector(setX:)],
               [x methodForSelector:@selector(setX:)]);
        NSLog(@"\n\tUsing libobjc functions, normal setX: is %p, overridden setX: is %p\n",
               method_getImplementation(class_getInstanceMethod(object_getClass(control),
                                                                @selector(setX:))),
               method_getImplementation(class_getInstanceMethod(object_getClass(x),
                                                                @selector(setX:))));
    }

    return 0;
}

